/*
 * @Author: wuqingchun
 * @Date: 2024-05-25 17:44:55
 * @Description: 
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-05-26 10:16:55
 */
#include <thread>
#include <vector>
#include <iostream>
#include <mutex>
#include <type_traits>

template <typename INT_TYPE>
class LockCounter
{
    static_assert(std::is_integral<INT_TYPE>::value, "T must be integral");
public:
    INT_TYPE FetchAdd(INT_TYPE step)
    {
        std::lock_guard <std::mutex> objLG(m_objMtx);
        INT_TYPE oldval = m_value;
        m_value += step;
        return oldval; 
    }

    INT_TYPE Load()
    {
        return m_value;
    }

private:
    std::mutex m_objMtx;
    INT_TYPE m_value;
};


int main(int argc, char** argv)
{
    LockCounter<uint64_t> objCounter;
    std::vector<std::thread> vecThreads;

    if (argc < 2)
    {
        std::cout << "Usage: " << argv[0] << " thread-number" << std::endl;
        return 0;
    }

    for (uint32_t uiIndex = 0; uiIndex < atoi(argv[1]); uiIndex++)
    {
        vecThreads.push_back(std::thread([&]()
        {
            uint32_t uiTimes = 0;
            while (uiTimes < 1000000)
            {
                objCounter.FetchAdd(1);
                uiTimes++;
            }
        }));
    }
    
    for (auto& refThread : vecThreads)
    {
        refThread.join();
    }

    vecThreads.clear();

    
    std::cout << "Counter: " << objCounter.Load() << std::endl;

    return 0;
}